﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using CoreEx.Common.Proxy;
using LinFu.AOP.Interfaces;
using CoreEx.DynamicInvoker;
using LinFu.IoC.Configuration;
using LinFu.IoC.Interfaces;
using LinFu.IoC;
using LinFu.Proxy.Interfaces;
using Mono.Cecil;
using CoreEx.Common.Extensions;

namespace CoreEx.Common.Implementation.Proxy
{
    [Implements(typeof(IInvokeWrapper), ServiceName = "ProxyMethodBuilderInterceptor")]
    public class ProxyMethodBuilderInterceptor : IInvokeWrapper, IInitialize
    {
        private readonly IMethodBuilder _actualMethodBuilder;
        
        private IEnumerable<IMethodModifier> _modificators;

        public ProxyMethodBuilderInterceptor(IMethodBuilder actualMethodBuilder)
        {
            _actualMethodBuilder = actualMethodBuilder;
        }

        public void BeforeInvoke(IInvocationInfo info)
        {
            var typeDefinition = (TypeDefinition)info.Arguments[0];
            var methodInfo = (MethodInfo)info.Arguments[1];
            _modificators.ForEach(m => m.BeforeConstruction(typeDefinition, methodInfo));   
        }

        public void AfterInvoke(IInvocationInfo info, object returnValue)
        {                                               
            var methodDefinition = (MethodDefinition) returnValue;
            var typeDefinition = (TypeDefinition) info.Arguments[0];
            var methodInfo = (MethodInfo) info.Arguments[1];
            _modificators.ForEach(m => m.AfterConstruction(typeDefinition,methodInfo, methodDefinition));   
        }

        public object DoInvoke(IInvocationInfo info)
        {
            return info.TargetMethod.DynamicInvoke(_actualMethodBuilder, info.Arguments);
        }

        #region IInitialize<IServiceContainer> Members

        public void Initialize(IServiceContainer source)
        {
            _modificators = source.GetServices<IMethodModifier>(); 
        }

        #endregion
    }
}